﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using CID.Domain.Infrastructure;
using CID.Support.BinaryContentConverters;

namespace CID.Web.Support.TemplateContentEdition
{
    internal sealed class TemplateContentEditorRegistry
    {
        public static readonly TemplateContentEditorRegistry Instance = new TemplateContentEditorRegistry();

        private List<Assembly> assembliesAlreadyInspectedForBinaryContentConverters;
        private List<string> availableTemplateContentEditorConverterTypes;

        public TemplateContentEditor DefaultEditor { get; private set; }

        private TemplateContentEditorRegistry()
        {
            DefaultEditor = new TemplateContentEditor(new UnicodeBinaryContentConverter(), new PartialViewUserInterfaceDefinition("DefaultEditor"));
            availableTemplateContentEditorConverterTypes = new List<string>();
            assembliesAlreadyInspectedForBinaryContentConverters = new List<Assembly>();
            RegisterAssemblyToInspectForBinaryContentConverters(typeof(IBinaryContentConverter).Assembly, false);
        }

        #region AvailableTemplateContentEditorConverterTypes members
        public IEnumerable<string> GetAvailableTemplateContentEditorConverterTypes()
        {
            return availableTemplateContentEditorConverterTypes;
        }

        public void RegisterAssemblyToInspectForBinaryContentConverters(Assembly assembly, bool versionSpecific)
        {
            if (!assembliesAlreadyInspectedForBinaryContentConverters.Contains(assembly))
            {
                var binaryContentConverterTypes = assembly.GetTypes().Where(x => x.IsClass && !x.IsAbstract && typeof(IBinaryContentConverter).IsAssignableFrom(x));
                foreach (var binaryContentConverterType in binaryContentConverterTypes)
                {
                    var binaryContentConverterTypeName = versionSpecific ? 
                        binaryContentConverterType.AssemblyQualifiedName : 
                        String.Format("{0}, {1}", binaryContentConverterType.FullName, assembly.GetName().Name);
                    availableTemplateContentEditorConverterTypes.Add(binaryContentConverterTypeName);
                }

                assembliesAlreadyInspectedForBinaryContentConverters.Add(assembly);
            }
        }
        #endregion

        #region AvailableTemplateContentEditorViewNames members
        public IEnumerable<string> GetAvailableTemplateContentEditorViewNames()
        {
            List<string> result = new List<string>();

            var availableFiles = Directory.GetFiles(TemplateContentEditorViewsBasePath, "*.cshtml");
            foreach (var file in availableFiles)
                result.Add(Path.GetFileNameWithoutExtension(file));

            return result;
        }

        public string TemplateContentEditorViewsBasePath { get; set; }
        #endregion

        public TemplateContentEditor GetEditor(ITemplateType templateType)
        {
            var result = DefaultEditor;

            var converterType = Type.GetType(templateType.TemplateContentEditorConverterType);
            if ((converterType != null) && !String.IsNullOrEmpty(templateType.TemplateContentEditorViewName))
                result = new TemplateContentEditor((IBinaryContentConverter) Activator.CreateInstance(converterType), new PartialViewUserInterfaceDefinition(templateType.TemplateContentEditorViewName));

            return result;
        }
    }
}